function Database () { }
Database.create = function (name, element)
{
	var object = {
	
		name 		: name,
		username 	: '',
		password 	: '',
		server 		: '',
		values 		: [],
		tables 		: [], 
		pagesize	: 100,
		SHOWOPTIONS	: false,
		SHOWEXPORT	: false, 
		setoptions	: function () { this.SHOWOPTIONS=!this.SHOWOPTIONS; Event.reload(); }, 
		setexport	: function () { this.SHOWEXPORT=!this.SHOWEXPORT; Event.reload(); }, 
		 
		load		: function (element)
		{ 
			for (var m=0;m<element.attributes.length;m++)
			{
				this[ element.attributes[m].name ] = element.attributes[m].value; 
				this.values.push (element.attributes[m].name);
			}  
		},
		
		getobjects 	: function ()
		{  
			Webservice.getobjects ('database', this.name,
								   'user', this.username,
								   'password', this.password,
								   'server', this.server,
								   'pagesize', this.pagesize );                      
		}, 
		
		getobject 	: function (key)
		{ 
			Webservice.getobject ('table', key,
								   'database', this.name,
								   'user', this.username,
								   'password', this.password,
								   'server', this.server,
								   'pagesize', this.pagesize );                      
		}, 
		
		createquery : function (text, position, nodename)
		{ 
			var xml=[], node=nodename||'query';
			xml.push ('<' + node + ' ');
			xml.push (' database="' + this.name + '" ');
			xml.push (' user="' + this.username + '" ');
			xml.push (' password="' + this.password + '" ');
			xml.push (' server="' + this.server + '" '); 
			xml.push (' pagesize="' + this.pagesize + '" '); 
			xml.push (' start="' + position + '"><![CDATA[' + text + ']]></' + node + '>');
			return xml.join ('');
		}, 
		
		add 		: function (name)
		{ 
			var sql = this.createquery("CREATE TABLE "+name+" (id int (11))");      
			var me 	= this.name;
			this.request = Webservice.post (sql, function (x) 
			{ 
				alert (x) 
				Controller.databases[me].getobjects ();
			});          
		}, 
		
		save 		: function (name)
		{ 
			var sql = this.createquery('', '', 'create');      
			this.request = Webservice.post (sql, function (x) 
			{ 
				alert (x);  
				start ();
			});          
		}, 
		
		destruct	: function ()
		{ 
			if (!confirm ('are you sure you want to delete databse '+this.name+'?')) return false;
			var sql = this.createquery('', '', 'remove');      
			this.request = Webservice.post (sql, function (x) 
			{ 
				alert (x);  
				start ();
			});          
		}, 
		
		remove 		: function (name)
		{ 
			if (!confirm ('are you sure you want to delete table '+name+'?')) return false;
			var sql = this.createquery("DROP TABLE "+name+"");      
			var me 	= this.name;
			this.request = Webservice.post (sql, function (x) 
			{ 
				alert (x) 
				Controller.table = null;
				Controller.databases[me].getobjects ();
			});          
		}, 
		
		rename 		: function (oldname, newname)
		{ 
			var sql = this.createquery("ALTER TABLE "+oldname+" RENAME TO "+newname+"");      
			var me 	= this.name;
			this.request = Webservice.post (sql, function (x) 
			{ 
				alert (x) 
				Controller.table = null;
				Controller.databases[me].getobjects ();
			});          
		} 
	
	
	};
	if (element) object.load (element);
	return object;
}

function QueryBuilder () {}
QueryBuilder.create = function (database)
{ 
	var o={
		tables    : {},
		database  : database,
		hascolumn : function (table, name) { var o=this.tables[table].columns; for (var e in o) {if (o[e]==name)return true;} return false; },
		addcolumn : function (table, name) { if (this.hascolumn(table,name)) return this.delcolumn(table,name); this.tables[table].columns.push (name); },
		delcolumn : function (table, name) { var o=[],a=this.tables[table].columns;
                                             for (var e in a) {if (a[e]!=name)o.push(a[e]);} 
                                             this.tables[table].columns=o; return o; },
		deltable  : function (table) { var o=[],a=this.tables;for (var e in a) {
                                       if (a[e].name!=table)o[e]=a[e];} this.tables=o; return o; }, 
		addtable  : function (name) { if (this.tables[name]) return true; 
                                      this.tables[name] = { name:name,columns:[],
                                      addcolumn:function(x) { this.columns.push(x); } } },
		render    : function ()
		{
			var table, sql=['SELECT'], tables=[], fields=[];
			for (var x in this.tables)
			{
				table=this.tables[x];
				tables.push (table.name);
				if (table.columns.length > 0)
				{
					for (var c in table.columns)
					{
					    fields.push (table.name + '.' + table.columns[c]);
					}
				}
				else
				{
					fields.push (table.name + '.*');
				}
			}
			
			sql.push (fields.join (', '));
			sql.push ('FROM');
			sql.push (tables.join (', ')); 
			return sql.join ('\n');
		}
	}
	return o;
}


function Query () {}
Query.create = function (text, name, database)
{ 
    var o={
       name 	 : name,
       database  : database,
       text 	 : text,
       result 	 : null,
       SQLON 	 : true,
       request 	 : null,  
       loadtable : function (name) { var query=this, response=function(data) 
	                 { Controller.ontable (data, function ()  
                     { Controller.querycollection.selected=query;query.addx (name);});} 
					qbuilder.innerHTML='loading...';
					Webservice.getobject (
					  'table', name,
					  'database', this.database.name,
					  'user', this.database.username,
					  'password', this.database.password,
					  'server', this.database.server,
					  'pagesize', this.database.pagesize, response ); },
       builder 	 : QueryBuilder.create(database),
       deltable  : function (table) { this.builder.deltable (table); this.text = this.builder.render(); Event.reload(); },
       addx      : function (name) { this.builder.addtable (name); this.text = this.builder.render(); Controller.setvalue ("querytable", name); },
       add       : function (name) { this.loadtable (name);  },
       addcolumn : function (table, name) { var o=qbuilder.scrollTop; this.builder.addcolumn (table, name); this.text = this.builder.render(); Event.reload();  qbuilder.scrollTop=o; },
       hascolumn : function (table, name) { var o=this.builder.tables[table].columns; for (var e in o) {if (o[e]==name)return true;} return false;  },
       pagesize	 : 100,
       select 	 : function (x) { this.selected=this.selected==x?-1:x;Event.reload(); },
       sql 		 : function (x) { this.SQLON=!this.SQLON;Event.reload(); },
       advance	 : function (x) { this.selected+=x; Event.reload();},
       selected  : -1,
       position  : 0,
       count 	 : 0, 
       height 	 : 100, 
	   
       update : function (text, callback)
       {  
          this.request = Webservice.post (this.database.createquery (text, 0), callback);
	   },
	   
       setvalue : function (name, index, value)
       {     
			var records  = this.result.getElementsByTagName ('record');
			var field    = records[index].childNodes;
			for (var x=0;x<field.length;x++)
			{ 
				if(field[x].nodeName=='field' && field[x].getAttribute ("name")==name)
				{ 
					if (field[x].firstChild) field[x].firstChild.nodeValue = value;
					else 
					{
						field[x].appendChild (this.result.createCDATASection (value)); 
					}
				}  
			}
	   },
	   
       invoke : function ()
       {  
	   	  this.database.pagesize = this.pagesize;
          this.request = Webservice.post (this.database.createquery (this.text, this.position), function (data, id)
          {
              var o=Controller.querycollection.items;
              for (var x=0;x<o.length;x++)
              {
                 if (id==o[x].request)
                 {
                     
                     var dom=XmlDocument.create();   
                     if (dom.loadXML (data))  
                     {  
                         o[x].result = dom;
                         Controller.querycollection.index = x;
                         Controller.querycollection.selected = o[x];
                         querier.invoke ();
                     }
                 }
              }
          });
       }
    } 
	
	o.key = database.name + '.' + name;
	return o;
}


function Table () {}
Table.create = function (node, dbobject)
{
	var object= { 
		node 		: node, 
		load 		: function() { var o=this.node.attributes;for (var e=0;e<o.length;e++) this[o[e].name]=o[e].value}, 
		database 	: dbobject, 
		selected 	: null, 
		key 		: null, 
		columns 	: [], 
		index 	    : 0, 
		backupobject : function ()
		{  
			var sql = this.database.createquery (this.name,this.index,'backup');
			Webservice.post (sql, function (x)
			{
				Controller.table.index += 100;
				var count,dom=XmlDocument.create();    
				if (dom.loadXML (x))  
				{ 
				    var tables  = dom.getElementsByTagName ('recordset');
					for (var i=0;i<tables.length;i++)
					{
						count=tables[i].getAttribute ('count');
						if (count > Controller.table.index)
						{
                            show_wait_message ('backing up '+Controller.table.name+' '+
											   (Controller.table.index+1)+' of ' + count + '...');
							Controller.table.backupobject ();
						}
						else
						{
							show_wait_message ('backup of '+textlink(Controller.table.name,'window.open("'+Controller.table.name+'.backup.txt")')+' complete!' +
										'...' + textlink ('back', 'main.invoke()'));
						}
					}
				}
			});
		},
		drop 		: function (name)
		{ 
			if (!confirm ('are you sure you want to delete column '+name+'?')) return false;
			var sql = 'ALTER TABLE ' + this.name + ' DROP COLUMN ' + name;
			var my	= this.database.name;
			var me	= this.name;
			sql = this.database.createquery (sql, 0); 
			this.request = Webservice.post (sql, function (x) 
			{  
				alert (x);
				Controller.table.selected = null;
				Controller.databases[my].getobject (me);
			});
		} , 
		add 		: function (name)
		{ 
			var sql = 'ALTER TABLE ' + this.name + ' ADD ' + name + ' VARCHAR (50)';
			var my	= this.database.name;
			var me	= this.name;
			sql = this.database.createquery (sql, 0); 
			this.request = Webservice.post (sql, function (x) 
			{  
				alert (x);
				Controller.table.selected = name;
				Controller.databases[my].getobject (me);
			});
		} ,
		doexport    : function ()
		{           
			var column=[], script = 'DROP TABLE IF EXISTS ' + this.name + '\nCREATE TABLE ' + this.name + ' ( \n';   
			for (var e in this.columns)
			{	 
				column.push ( '    ' + this.columns[e].doexport () );     
			}                 
			script += column.join (',\n') + ')\n';
			if (this.columns.length > 0) return script;
			else return '';
		} ,
		draw        : function ()
		{
			var htm=[] 
			htm.push ('<tr>');
		    htm.push ('<td title="edit '+this.name+'" class=header>' + imagelink(PIC_ROOT+'/webservices/images/ico_grid.jpg', 'Controller.databases["' + this.database.name + '"].getobject ("' + this.name + '")' ) + '</td>');
		    htm.push ('<td title="open '+this.name+'" class=header>' + imagelink(PIC_ROOT+'/webservices/images/explorer/icon_book.gif', 'Controller.openobject("'+this.name+'",null,"'+this.database.name+'")' ) + '</td>');
			htm.push ('<td title="drop '+this.name+'" class=header>' + imagelink(PIC_ROOT+'/webservices/images/delete.gif', 'Controller.deletetable("'+this.name+'")' ) + '</td>');
		    htm.push ('<td class=header nowrap>' + textlink(this.name, 'Controller.databases["' + this.database.name + '"].getobject ("' + this.name + '")') + '&nbsp;</td>');
			htm.push ('<td class=header nowrap>' + this.type + '&nbsp;</td>');
			htm.push ('<td class=header nowrap align="right">' + this.size + '&nbsp;</td>');
			htm.push ('<td class=header nowrap align="right">' + this.free + '&nbsp;</td>');
			htm.push ('<td class=header nowrap>' + this.created + '&nbsp;</td>');
			htm.push ('<td class=header nowrap>' + this.updated + '&nbsp;</td>');
			htm.push ('<td class=header nowrap>&nbsp;</td>');
			htm.push ('</tr>');
			return htm.join ('');
		}
	};
	object.load();
	return object;
}






function Column () {} 
Column.create=function(element, table)
{
    var o={
        size 	: '',
        fields 	: ['size'],
        table 	: table,
        draw 	: function (selected)
        {
           var type, css=' style="font-size:8pt" class=flat ', htm=[];
           htm.push ('<tr>');
           if (selected && selected==this.name)
           {
               htm.push ('<td class=header>' + imagelink(PIC_ROOT+'/webservices/images/back.bmp', 'Controller.setobject(null)') + '</td>');
               htm.push ('<td class=header>' + imagelink(PIC_ROOT+'/webservices/images/explorer/i.p.save.gif', 'Controller.savecolumn("'+this.name+'")' ) + '</td>');
               htm.push ('<td class=header><input ' + css + ' onchange=\'column_set("name",this.value)\' size=15 value="' + this.name + '"></td>');
               htm.push ('<td class=header>');
               htm.push ('<select class=small onchange=\'column_set("type",this.value)\'>');
			   for (var n in DATATYPE)
			   {
			   		type = DATATYPE[n].toLowerCase();
			   	    htm.push ('<option '+sel(type==this.type)+' value="' + type + '">' + type + '</option>');
			   }
               htm.push ('</select>');
               htm.push ('</td>');
               htm.push ('<td class=header><input ' + css + ' onchange=\'column_set("size",this.value)\' size=2 value="' + this.size + '"></td>');
               htm.push ('<td class=header align="center"><input onclick=\'column_set("allownull",this.checked?1:0)\' '+chk(this.allownull.length>0)+' type=checkbox value="' + this.allownull + '"></td>');
               htm.push ('<td class=header align="center"><input onclick=\'column_set("key",this.checked)\' '+chk(this.key.length>0)+' type=checkbox value="' + this.key + '"></td>');
               htm.push ('<td class=header align="center"><input onclick=\'column_set("extra",this.checked?"auto_increment":"")\' '+chk(this.extra.length>0)+' type=checkbox value="' + this.extra + '"></td>');
               htm.push ('<td class=header><input ' + css + ' onchange=\'column_set("defaultvalue",this.value)\' size=2 value="' + this.defaultvalue + '"></td>');
               htm.push ('<td class=header>&nbsp;</td>');
           }
           else
           {
               htm.push ('<td class=header>' + imagelink(PIC_ROOT+'/webservices/images/explorer/i.p.edit.gif', 'Controller.setobject("'+this.originalname+'")' ) + '</td>');
               htm.push ('<td class=header>' + imagelink(PIC_ROOT+'/webservices/images/delete.gif', 'Controller.table.drop("'+this.originalname+'")' ) + '</td>');
               htm.push ('<td class=header>' + textlink(this.name, 'Controller.setobject("'+this.originalname+'")', 'font-size:8pt') + '&nbsp;</td>');
               htm.push ('<td class=header>' + this.type + '&nbsp;</td>');
               htm.push ('<td class=header>' + this.size + '&nbsp;</td>');
               htm.push ('<td class=header align="center">' + this.allownull + '&nbsp;</td>');
               htm.push ('<td class=header align="center">' + this.key + '&nbsp;</td>');
               htm.push ('<td class=header align="center">' + this.extra + '&nbsp;</td>');
               htm.push ('<td class=header>' + this.defaultvalue + '&nbsp;</td>');
               htm.push ('<td class=header>&nbsp;</td>');
           }
           htm.push ('</tr>');
           return htm.join ('');
        },
        doexport : function ()
        {
            var query=[]; 
			query.push (' ' + this.name);
			query.push (' ' + this.type);
			if (this.size && this.size.length > 0) query.push (' (' + this.size + ') ');
			if (this.allownull && this.allownull.length > 0) query.push (' NULL ');
			else query.push (' NOT NULL ');
			if (this.defaultvalue && this.defaultvalue.length > 0) query.push (' DEFAULT ' + this.defaultvalue);
			query.push (' ' + this.extra + ' ');
			if (this.key) query.push (' PRIMARY KEY ');
			return query.join (''); 
        },
        save : function ()
        {
            var htm=[], query=[]; 
			query.push ('ALTER TABLE ' + Controller.table.name);
			query.push (' CHANGE ' + this.originalname);
			query.push (this.doexport());
//			query.push (' ' + this.name);
//			query.push (' ' + this.type);
//			if (this.size && this.size.length > 0) query.push (' (' + this.size + ') ');
//			if (this.allownull && this.allownull.length > 0) query.push (' NULL ');
//			else query.push (' NOT NULL ');
//			if (this.defaultvalue && this.defaultvalue.length > 0) query.push (' DEFAULT ' + this.defaultvalue);
//			query.push (' ' + this.extra + ' ');
//			if (this.key) query.push (' PRIMARY KEY ');
			var sql = query.join (''); 
			if (Controller.databasename && Controller.databases[Controller.databasename])
			{ 
				sql = Controller.databases[Controller.databasename].createquery (sql, 0); 
				this.request = Webservice.post (sql, function (x) 
				{ 
					alert (x)
					Controller.table.selected = null;
					Controller.databases[Controller.databasename].getobject (Controller.table.name);
				});
			} 
			return sql;
        }
    };
    var e=element.attributes;
    for (var x=0;x<e.length;x++) { o.fields.push(e[x].name); o[e[x].name]=e[x].value ; };
    var mm=re.exec (o.type);
    if (mm)
    {  
        o.type = mm[1];
        o.size = mm[2];
    }
	o.originalname = o.name;
    return o;
}












